package com.jiyongjun.component.utils;

import com.jiyongjun.component.enums.LogConstant;
import com.jiyongjun.component.exception.BizException;
import lombok.extern.slf4j.Slf4j;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.executable.ExecutableValidator;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.Set;

/**
 * <h2></h2>
 * <h3>描述：</h3>
 *
 * @author yongjun.jyj
 * @since 2022/7/14 18:17
 */
@Slf4j
public class ParamValidator {
    private static final Validator VALIDATOR = Validation.buildDefaultValidatorFactory().getValidator();

  /**
   * 校验实体参数,返回第一条错误信息
   *
   * @param t 入参
   * @param <T> 入参泛型
   */
  public static <T> void validate(T t, Class<?>... groups) {
    if (t == null) {
      return;
    }
    Set<ConstraintViolation<T>> validationSet = VALIDATOR.validate(t, groups);
    if (validationSet != null && validationSet.size() > 0) {
      ConstraintViolation<T> violation = validationSet.iterator().next();
      String message = MessageFormat.format("字段[{0}]：{1}", violation.getPropertyPath(), violation.getMessage());
      throw new BizException(LogConstant.FAIL_BIZ_PARAM_AUTO_VALIDATE_ERROR, message);
    }
  }

  /**
   * 校验方法入参
   *  @param <T> 要校验的方法所属的实例对象
   * @param method 要校验的方法
   * @param args 入参
   */
  public static <T> void validateParameters(T targetInstance, Method method, Object[] args, Class<?>... groups) {
    if (args == null) {
      return;
    }
    ExecutableValidator executableValidator = VALIDATOR.forExecutables();
    Set<ConstraintViolation<T>> validationSet = executableValidator.validateParameters(targetInstance, method, args, groups);
    if (validationSet != null && validationSet.size() > 0) {
      ConstraintViolation<T> violation = validationSet.iterator().next();
      String propertyPath = violation.getPropertyPath().toString();
      propertyPath = propertyPath.substring(propertyPath.indexOf(".") + 1);
      if (propertyPath.startsWith("arg")) {
        try {
          int argIdx = Integer.parseInt(propertyPath.substring("arg".length(), propertyPath.contains(".") ? propertyPath.indexOf(".") : propertyPath.length()));
          String argName = method.getParameters()[argIdx].getName();
          propertyPath = argName + propertyPath.substring(("arg" + argIdx).length());
        } catch (NumberFormatException e) {
          log.warn("转换参数名称错误（不影响业务）|exception|msg={}", e.getMessage());
        }
      }
      String message = MessageFormat.format("字段[{0}]：{1}", propertyPath, violation.getMessage());
      throw new BizException(LogConstant.FAIL_BIZ_PARAM_AUTO_VALIDATE_ERROR, message);
    }
  }
}
